// The Swift Programming Language
// https://docs.swift.org/swift-book

import SwiftUI
import FMDB

public enum ATDBError: Error {
    case none
    case unknown
    case executeError(String)
}

public class ATDBManager: NSObject {
    
    var dbqueue: FMDatabaseQueue?
    var db: FMDatabase?
    
    public static let manager = ATDBManager()
    
    public func setupDB(dbPath: String) {
        print("db path: \(dbPath)")
        var newDbPath = dbPath
        newDbPath.append("/db.sqlite")
        dbqueue = FMDatabaseQueue(path: newDbPath)
        if dbqueue == nil {
            print("dbqueue创建失败")
        }
        dbqueue?.inDatabase({ database in
            database.open()
        })
    }
    
    //MARK: - public
    public func createTable(sql: String) {
        var executeError: Error?
        dbqueue?.inDatabase({ database in
            do {
                try database.executeUpdate(sql, values: nil)
            } catch {
                executeError = error
            }
        })
        if let error = executeError {
            print("db error: \(error)")
        }
    }
    
    public func search(sql: String, parserBolock: (FMResultSet) -> Any) -> Result<[Any],ATDBError> {
        var executeError: Error?
        var dataArray: [Any]?
        dbqueue?.inDatabase({ database in
            do {
                dataArray = []
                let result = try database.executeQuery(sql, values: nil)
                while result.next() {
                    let model = parserBolock(result)
                    dataArray?.append(model)
                }
            } catch  {
                executeError = error
            }
        })
        if let array = dataArray {
            return Result.success(array)
        } else if let error = executeError {
            print("db error: \(error)")
            return Result.failure(ATDBError.executeError(error.localizedDescription))
        } else {
            return Result.failure(ATDBError.unknown)
        }
    }
    
    public func delete(sql: String) -> Result<Bool,ATDBError> {
        var executeError: Error?
        dbqueue?.inDatabase({ database in
            do {
                let _ = try database.executeQuery(sql, values: nil)
            } catch {
                executeError = error
            }
        })
        if let error = executeError {
            print("db error: \(error)")
            return Result.failure(ATDBError.executeError(error.localizedDescription))
        }
        return Result.success(true)
    }
    
    public func insert(sql: String) -> Bool {
        var executeError: Error?
        dbqueue?.inDatabase({ database in
            do {
                try database.executeUpdate(sql, values: nil)
            } catch {
                executeError = error
            }
        })
        if let error = executeError {
            print("db error: \(error)")
            return false
        }
        return true
    }
    
    public func update(sql: String, values: [Any]) -> Bool {
        var executeError: Error?
        dbqueue?.inDatabase({ database in
            do {
                try database.executeUpdate(sql, values: values)
            } catch {
                executeError = error
            }
        })
        if let error = executeError {
            print("db error: \(error)")
            return false
        }
        return true
    }
}
